"""
微信机器人核心模块
"""

import time
import os
import pyautogui
import subprocess
from typing import List, Optional, Dict, Any
from ..config import ConfigManager
from ..utils import ImageUtils, AutomationUtils, setup_logger
from ..utils.csv_utils import CSVUtils
from .database import DatabaseManager


class WeChatRobot:
    """微信机器人主类"""
    
    def __init__(self, config_manager: ConfigManager = None):
        """
        初始化微信机器人
        
        Args:
            config_manager: 配置管理器
        """
        self.config_manager = config_manager or ConfigManager()
        self.automation_config = self.config_manager.get_automation_config()
        self.app_config = self.config_manager.get_app_config()
        self.logging_config = self.config_manager.get_logging_config()
        
        # 初始化工具类
        self.image_utils = ImageUtils(
            confidence_levels=self.automation_config.get('confidence_levels', [0.8, 0.7, 0.6, 0.5]),
            max_retries=self.automation_config.get('max_retries', 3)
        )
        self.automation_utils = AutomationUtils(
            wait_time=self.automation_config.get('wait_time', 1.0)
        )
        self.database_manager = DatabaseManager(self.config_manager)
        self.csv_utils = CSVUtils(self.config_manager)
        
        # 初始化日志
        self.logger = setup_logger('wechat_robot', self.logging_config)
        
        # 获取项目根目录路径
        self.project_root = self._get_project_root()
        
        # 图像文件路径映射（使用绝对路径）
        self.image_files = {
            'address_book': os.path.join(self.project_root, 'assets', 'images', 'address_book.png'),
            'new_customer': os.path.join(self.project_root, 'assets', 'images', 'new_customer.png'),
            'add': os.path.join(self.project_root, 'assets', 'images', 'add.png'),
            'add_o': os.path.join(self.project_root, 'assets', 'images', 'add_o.png'),
            'lastadd': os.path.join(self.project_root, 'assets', 'images', 'lastadd.png'),
            'wechat': os.path.join(self.project_root, 'assets', 'images', 'wechat.png'),
            'send': os.path.join(self.project_root, 'assets', 'images', 'send.png'),
            'del': os.path.join(self.project_root, 'assets', 'images', 'del.png'),
            'ok': os.path.join(self.project_root, 'assets', 'images', 'ok.png')
        }
    
    def _get_project_root(self) -> str:
        """
        获取项目根目录路径
        
        Returns:
            项目根目录的绝对路径
        """
        # 获取当前文件的目录
        current_dir = os.path.dirname(os.path.abspath(__file__))
        
        # 向上查找包含 main.py 的目录（项目根目录）
        while current_dir != os.path.dirname(current_dir):  # 直到到达文件系统根目录
            if os.path.exists(os.path.join(current_dir, 'main.py')):
                return current_dir
            current_dir = os.path.dirname(current_dir)
        
        # 如果找不到，返回当前工作目录
        return os.getcwd()
    
    def log_step(self, action: str):
        """
        记录步骤日志
        
        Args:
            action: 操作描述
        """
        self.logger.info(f"开始执行：{action}")
        # print(f"开始执行：{action}")
    
    def get_mobiles(self, page: int = 0) -> List[str]:
        """
        获取手机号列表
        
        Args:
            page: 页码
            
        Returns:
            手机号列表
        """
        data_source_config = self.config_manager.get_data_source_config()
        data_source_type = data_source_config.get('type', 'database')
        page_size = data_source_config.get('page_size', 10)
        
        if data_source_type == 'csv':
            self.log_step('CSV文件中查询手机号')
            return self.csv_utils.get_mobiles_from_csv(page)
        else:
            self.log_step('数据库中查询手机号')
            start = page * page_size
            return self.database_manager.get_mobiles(start, page_size)
    
    def fill_message(self) -> bool:
        """
        填写添加好友消息
        
        Returns:
            是否成功
        """
        self.log_step('查询信息')
        
        message = self.database_manager.get_message()
        print(f"填写消息: {message}")
        return self.automation_utils.type_text(message, clear_first=True)
    
    def send_invite(self) -> bool:
        """
        发送添加好友请求
        
        Returns:
            是否成功
        """
        self.log_step('发送添加好友请求')
        
        invite = self.image_utils.locate_image_with_retry(self.image_files['send'])
        if invite:
            success = self.automation_utils.click_at_location(invite, offset_x=28, offset_y=25)
            if success:
                time.sleep(2)
                return True
        
        self.logger.warning('未找到发送按钮')
        return False
    
    def add_friend(self) -> bool:
        """
        添加好友操作
        
        Returns:
            是否成功
        """
        self.log_step('点击添加好友按钮')
        
        wechat = self.image_utils.locate_image_with_retry(self.image_files['wechat'], 1, [0.8])
        add = self.image_utils.locate_image_with_retry(self.image_files['lastadd'], 1, [0.8])
        
        if add and wechat:
            # 计算点击位置（基于wechat和add的位置）
            a_y = wechat.top
            a_x = add.left
            a_pos_x = a_x // 2 + 28
            a_pos_y = a_y // 2 + 25
            
            self.automation_utils.move_mouse(a_pos_x, a_pos_y)
            self.automation_utils.click('left', 1)
            time.sleep(1)
            
            # 填写消息并发送
            self.fill_message()
            time.sleep(1)
            return self.send_invite()
        else:
            self.logger.warning('未找到微信或添加按钮')
            self.click_ok()
            return False
    
    def click_ok(self) -> bool:
        """
        点击确定按钮
        
        Returns:
            是否成功
        """
        self.log_step('点击确定')
        
        ok_button = self.image_utils.locate_image_with_retry(self.image_files['ok'])
        if ok_button:
            return self.automation_utils.click_at_location(ok_button, offset_x=8, offset_y=8)
        else:
            self.logger.warning('未找到确定按钮')
            return False
    
    def delete_mobile(self) -> bool:
        """
        删除手机号
        
        Returns:
            是否成功
        """
        self.log_step('清除手机号')
        
        del_button = self.image_utils.locate_image_with_retry(self.image_files['del'])
        if del_button:
            return self.automation_utils.click_at_location(del_button, offset_x=8, offset_y=8)
        else:
            self.logger.warning('未找到删除按钮')
            return False
    
    def input_mobile(self) -> bool:
        """
        输入手机号
        
        Returns:
            是否成功
        """
        self.log_step('点击添加按钮')
        
        input_add = self.image_utils.locate_image_with_retry(self.image_files['add'])
        if not input_add:
            self.logger.warning('未找到添加按钮')
            return False
        
        self.automation_utils.click_at_location(input_add, offset_x=25, offset_y=25)
        # time.sleep(1)

        
        # 获取手机号列表
        page = self.config_manager.get('robot.db.page', 0)
        mobiles = self.get_mobiles(page)
        
        if not mobiles:
            self.logger.warning('没有可用的手机号')
            return False
        
        # 处理每个手机号
        success_count = 0
        for mobile in mobiles:
            self.logger.info(f"输入手机号：{mobile}")
            
            if self.automation_utils.type_text(mobile, clear_first=True):
                self.automation_utils.press_key('enter')
                time.sleep(3)
                
                if self.add_friend():
                    success_count += 1
                else:
                    self.logger.warning(f'添加好友失败,手机号: {mobile}')
                
                time.sleep(3)
                self.delete_mobile()
        
        self.logger.info(f"成功处理 {success_count}/{len(mobiles)} 个手机号")
        
        # 按ESC退出
        self.log_step('点击esc')
        self.automation_utils.press_key('esc')
        
        return success_count > 0
    
    def click_new_customer(self) -> bool:
        """
        点击新的客户
        
        Returns:
            是否成功
        """
        self.log_step('点击新的客户')
        
        new_customer_loc = self.image_utils.locate_image_with_retry(self.image_files['new_customer'], confidence_levels=[0.5, 0.4, 0.3])
        if not new_customer_loc:
            self.logger.warning('未找到新的客户按钮')
            return False
        
        # 右键点击
        pos_x, pos_y = self.automation_utils.calculate_click_position(new_customer_loc, 25, 25)
        self.automation_utils.move_mouse(pos_x, pos_y)
        self.automation_utils.click('right', 1)
        # time.sleep(1)
        
        # 左键点击
        self.automation_utils.move_mouse(pos_x + 5, pos_y + 5)
        self.automation_utils.click('left', 1)
        # time.sleep(1)
        
        return self.input_mobile()
    
    def locate_address_book(self) -> bool:
        """
        定位通信录
        
        Returns:
            是否成功
        """
        self.log_step('点击通信录')
        
        # 等待企业微信界面加载
        time.sleep(1)
        
        # 使用更低的置信度尝试识别
        location = self.image_utils.locate_image_with_retry(
            self.image_files['address_book'], 
            confidence_levels=[0.8]
        )
        if not location:
            self.logger.warning('未找到通信录按钮')
            # 拍摄调试截图
            screenshot_path = self.take_debug_screenshot()
            self.logger.info(f'已保存调试截图: {screenshot_path}')
            return False
        
        # 右键点击
        pos_x, pos_y = self.automation_utils.calculate_click_position(location, 25, 25)
        self.automation_utils.move_mouse(pos_x, pos_y)
        self.automation_utils.click('right', 1)
        
        # 左键点击
        self.automation_utils.move_mouse(pos_x + 5, pos_y + 5)
        self.automation_utils.click('left', 1)
        # time.sleep(1)
        
        # 移动到指定位置并点击
        self.automation_utils.move_mouse(pos_x + 200, pos_y + 30)
        self.automation_utils.click('left', 1)
        time.sleep(1)
        
        return self.click_new_customer()
    
    def check_accessibility_permissions(self) -> bool:
        """
        检查macOS辅助功能权限
        
        Returns:
            是否有权限
        """
        try:
            # 尝试执行一个简单的pyautogui操作来测试权限
            current_pos = pyautogui.position()
            self.logger.info(f"当前鼠标位置: {current_pos}")
            
            # 尝试移动鼠标（不实际移动，只是测试权限）
            pyautogui.moveTo(current_pos.x, current_pos.y, duration=0)
            
            self.logger.info("辅助功能权限检查通过")
            return True
            
        except Exception as e:
            self.logger.error(f"辅助功能权限检查失败: {e}")
            self.logger.error("请确保在 系统偏好设置 > 安全性与隐私 > 隐私 > 辅助功能 中")
            self.logger.error("为Python或Terminal添加权限")
            return False
    
    def launch_app_with_open_command(self) -> bool:
        """
        使用macOS的open命令启动企业微信应用
        
        Returns:
            是否成功
        """
        self.log_step('使用open命令启动企业微信')
        
        app_name = self.app_config.get('name', '企业微信')
        
        try:
            # 尝试使用open命令启动应用
            self.logger.info(f"使用open命令启动应用: {app_name}")
            result = subprocess.run(['open', '-a', app_name], 
                                 capture_output=True, text=True, timeout=10)
            
            if result.returncode == 0:
                self.logger.info("应用启动成功")
                time.sleep(5)  # 等待应用完全启动
                return True
            else:
                self.logger.error(f"open命令失败: {result.stderr}")
                return False
                
        except subprocess.TimeoutExpired:
            self.logger.error("open命令超时")
            return False
        except Exception as e:
            self.logger.error(f"使用open命令启动应用时发生错误: {e}")
            return False
    
    def launch_app(self) -> bool:
        """
        启动企业微信应用
        
        Returns:
            是否成功
        """
        self.log_step('启动企业微信')
        
        # # 首先尝试使用open命令（更可靠）
        # if self.launch_app_with_open_command():
        #     return True
        
        # self.logger.info("open命令失败，尝试使用Spotlight搜索")
        
        # 点击屏幕确保焦点
        self.automation_utils.click('left', 1)
        time.sleep(1)
        
        # 打开Spotlight搜索
        app_name = self.app_config.get('name', '企业微信')
        search_shortcut = self.app_config.get('search_shortcut', 'command+space')
        
        self.logger.info(f"尝试使用快捷键打开Spotlight: {search_shortcut}")
        self.logger.info(f"搜索应用名称: {app_name}")
        
        try:
            if search_shortcut == 'command+space':
                self.logger.info("执行 Command+Space 快捷键")
                self.automation_utils.hotkey('command', 'space')
            else:
                keys = search_shortcut.split('+')
                self.logger.info(f"执行快捷键: {keys}")
                self.automation_utils.hotkey(*keys)
            
            time.sleep(0.5)  # 增加等待时间让Spotlight完全打开
            
            # 输入应用名称
            self.logger.info(f"输入应用名称: {app_name}")
            if self.automation_utils.copy_paste(app_name):
                # time.sleep(2)
                self.logger.info("按Enter键启动应用")
                self.automation_utils.press_key('enter')
                time.sleep(1)  # 增加等待时间让企业微信完全启动
                self.logger.info("应用启动完成")
                return True
            else:
                self.logger.error("输入应用名称失败")
                return False
                
        except Exception as e:
            self.logger.error(f"启动应用时发生错误: {e}")
            return False
    
    def run(self) -> bool:
        """
        运行主程序
        
        Returns:
            是否成功
        """
        try:
            self.logger.info("启动微信机器人...")
            
            # 检查辅助功能权限
            if not self.check_accessibility_permissions():
                self.logger.error("缺少必要的系统权限，无法继续执行")
                return False
            
            # 根据数据源类型测试连接
            data_source_config = self.config_manager.get_data_source_config()
            data_source_type = data_source_config.get('type', 'database')
            
            if data_source_type == 'database':
                # 测试数据库连接
                if not self.database_manager.test_connection():
                    self.logger.error("数据库连接失败")
                    return False
            elif data_source_type == 'csv':
                # 测试CSV文件是否存在
                csv_file = data_source_config.get('csv_file', 'data/customer.csv')
                if not os.path.isabs(csv_file):
                    csv_file = os.path.join(self.project_root, csv_file)
                
                if not os.path.exists(csv_file):
                    self.logger.error(f"CSV文件不存在: {csv_file}")
                    return False
                
                # 测试CSV文件读取
                test_mobiles = self.csv_utils.get_mobiles_from_csv(0)
                if not test_mobiles:
                    self.logger.warning("CSV文件中没有找到手机号数据")
                else:
                    self.logger.info(f"CSV文件读取成功，找到 {len(test_mobiles)} 个手机号")
            
            # 启动应用
            if not self.launch_app():
                self.logger.error("启动企业微信失败")
                return False
            
            # 执行主要流程
            success = self.locate_address_book()
            
            if success:
                self.logger.info("机器人执行完成")
            else:
                self.logger.error("机器人执行失败")
            
            return success
            
        except Exception as e:
            self.logger.error(f"机器人执行过程中发生错误: {e}")
            return False
    
    def test_images(self) -> Dict[str, bool]:
        """
        测试所有图像识别
        
        Returns:
            测试结果
        """
        self.logger.info("开始测试图像识别...")
        
        # 获取所有图像文件
        image_files = list(self.image_files.values())
        results = self.image_utils.batch_test_images(image_files)
        
        return results
    
    def take_debug_screenshot(self) -> str:
        """
        拍摄调试截图
        
        Returns:
            截图文件路径
        """
        filename = f'debug_screenshot_{int(time.time())}.png'
        return self.image_utils.take_screenshot(filename)
